﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using UCL.Powersource.Analysis;

namespace UCL.Powersource.Statistics
{
    /// <summary>
    /// Statistic related to the number of invalid Backlog Items which are 
    /// those who either:
    ///  - have a 'Done' status when at least one of their tasks is not done
    ///  - do not have a 'Done' status when all their tasks are done
    ///  - have an invalid task
    /// </summary>
    [Export(typeof(IStatistic))]
    [DataContract(IsReference = true)]
    public class InvalidPBckLogItems : LinksRelatedWIStatisticsBase
    {
        [ExcludeFromCodeCoverage]
        public override string Label
        {
            get { return "Invalid Product Backlog Items"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Description
        {
            get { return "Number of Invalid Product Backlog Items in an iteration"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Name
        {
            get { return "InvalidPBckLogItems"; }
        }

        public static readonly Guid CN_Statistic_Guid = new Guid("D054DCC1-1BC8-4CD8-807C-C033024944E0");
       [ExcludeFromCodeCoverage]
        public override Guid Statistic_Guid
        {
            get { return CN_Statistic_Guid; }
        }

        
        private string PBIWithInvalidTasks { get { return _PBIWithInvalidTasks; } }
 
        private string PBINotDoneWithWorkItemDone { get { return _PBINotDoneWithWorkItemDone; } }

        private string PBIDoneWithUndoneItems { get { return _PBIDoneWithUndoneItems; } }

        /// <summary>
        /// Class fot invalid work item calculation
        /// </summary>
        /// <param name="collUri">tfs stat project collection Uri</param>
        /// <param name="iteration">Work item iteration</param>
        /// <param name="finishDate">Finish date</param>
        /// <param name="wiStore">Work item store</param>
        /// <returns>the number of invalid work item</returns>
        protected override int? CountInvalidWI(string collUri, string iteration, DateTime finishDate, WorkItemStore wiStore)
        {
            if (!linksCollectionCache.ContainsKey(collUri))
            {
                linksCollectionCache.Add(collUri, new Dictionary<string, Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>>());
                linksCollectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>());
                linksCollectionCache[collUri][iteration].Add("PBIDoneWithUndoneItems", new Dictionary<DateTime, WorkItemLinkInfo[]>());
                linksCollectionCache[collUri][iteration].Add("PBINotDoneWithWorkItemDone", new Dictionary<DateTime, WorkItemLinkInfo[]>());
                linksCollectionCache[collUri][iteration].Add("PBIWithInvalidTasks", new Dictionary<DateTime, WorkItemLinkInfo[]>());
            }
            else if (!linksCollectionCache[collUri].ContainsKey(iteration))
            {
                linksCollectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>());
                linksCollectionCache[collUri][iteration].Add("PBIDoneWithUndoneItems", new Dictionary<DateTime, WorkItemLinkInfo[]>());
                linksCollectionCache[collUri][iteration].Add("PBINotDoneWithWorkItemDone", new Dictionary<DateTime, WorkItemLinkInfo[]>());
                linksCollectionCache[collUri][iteration].Add("PBIWithInvalidTasks", new Dictionary<DateTime, WorkItemLinkInfo[]>());
            }

            List<int> wiList = new List<int>();

            queryLinkResults = GetQueryLinkResults(PBIDoneWithUndoneItems, collUri, finishDate, iteration, wiStore, "PBIDoneWithUndoneItems");
            wiList.AddRange(GetListOfIds(true, true, wiStore, iteration));

            queryLinkResults = GetQueryLinkResults(PBINotDoneWithWorkItemDone, collUri, finishDate, iteration, wiStore, "PBINotDoneWithWorkItemDone");
            wiList.AddRange(GetListOfIds(true, true, wiStore, iteration));

            queryLinkResults = GetQueryLinkResults(PBIWithInvalidTasks, collUri, finishDate, iteration, wiStore, "PBIWithInvalidTasks");
            wiList.AddRange(GetListOfIds(true, true, wiStore, iteration));

            return wiList.Select(p => p).Distinct().Count();
        }

        /// <summary>
        /// Product backlog items with undone items class
        /// </summary>
        [DataMember]
        private readonly string _PBIDoneWithUndoneItems = 
                "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE ([Source].[System.WorkItemType] = 'Product Backlog Item'  " +
                "AND  [Source].[State] = 'Done') " +
                "And ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') " +
                "AND (([Target].[System.WorkItemType] = 'Test Case' AND [Target].[State] = 'Design') OR " +
                "([Target].[System.WorkItemType] = 'Task' AND [Target].[State] <> 'Done'))" +
                "ORDER BY [System.Id] mode(MustContain) AsOf @AsOf";

        /// <summary>
        /// Product backlog items with done work items class
        /// </summary>
        [DataMember]
        private readonly string _PBINotDoneWithWorkItemDone =
                "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE  ([Source].[System.WorkItemType] = 'Product Backlog Item'  " +
                "AND [Source].[State] Not In ('Removed', 'Done')" +
                "AND  [Source].[System.RelatedLinkCount] > 0) " +
                "And ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') " +
                "And ([Target].[System.WorkItemType] <> ''  " +
                "AND [Target].[State] Not In ('Removed', 'Done'))" +
                "ORDER BY [System.Id] mode(DoesNotContain) AsOf @AsOf";

        /// <summary>
        /// Product backlog items with invalid tasks
        /// </summary>
        [DataMember]
        private readonly string _PBIWithInvalidTasks =
                "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE ([Source].[System.WorkItemType] = 'Product Backlog Item'  " +
                "AND  [Source].[State] <> 'Removed') " +
                "And ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') " +
                "And ([Target].[System.WorkItemType] = 'Task'  " +
                "AND  [Target].[Activity] = ''  " +
                "AND  [Target].[State] <> 'Removed') " +
                "ORDER BY [System.Id] mode(MustContain) AsOf @AsOf";
  
    }
}

